<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
	<style>
		#canvas-wrapper{
			width:1200px;
			height:800px;
			position:relative;
			margin:50px auto;
		}
		#canvas{
			border:1px solid #aaa;
		}
		#controller{
			position:absolute;
			top:30px;
			left:30px;
			background-color:rgba(0,85,116,0.7);
			padding:5px 20px 25px 20px;
			border-radius:10px 10px;
		}
		#controller h1{
			color:#FFF;
			font-weight:bold;
			font-family:Microsoft YaHei;
		}
		#controller #canvas-btn{
			display:inline-block;
			background-color:#8b0;
			color:#FFF;
			font-size:14px;
			padding:5px 15px;
			border-radius:6px 6px;
			text-decoration:none;
			margin-top:10px;
			margin-right:20px;
		}
		#controller #canvas-btn:hover{
			text-decoration:none;
			background-color:#7a0;
		}
		#controller .color-btn{
			display:inline-block;
			padding:5px 15px;
			border-radius:6px 6px;
			font-size:14px;
			margin-top:10px;
			margin-right:5px;
			text-decoration:none;
		}
		#controller .color-btn:hover{
			text-decoration:none;
		}
		#controller #white-color-btn{
			background-color:#FFF;
		}
		#controller #black-color-btn{
			background-color:#000;
		}
	</style>
</head>
<body>

<div id="canvas-wrapper">
	<canvas id="canvas"></canvas>
	<div id="controller">
		<h1>Canvas绘图之旅</h1>
		<a href="#" id="canvas-btn">停止运动</a>
		<a href="#" class="color-btn" id="white-color-btn">&nbsp;</a>
		<a href="#" class="color-btn" id="black-color-btn">&nbsp;</a>
	</div>
</div>
<script >
    var balls = [];
    var searchLight = {x:400, y:400, radius:150, vx:Math.random()*5+10, vy:Math.random()*5+10};
    var rot = 0;
    var isMoving = true;
    var themeColor = "white";
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
	var originalMoveTo = CanvasRenderingContext2D.prototype.moveTo;
	CanvasRenderingContext2D.prototype.lastMoveToLoc = {};

    CanvasRenderingContext2D.prototype.moveTo = function(x, y){
		originalMoveTo.apply(context, [x,y]);
		this.lastMoveToLoc.x = x;
		this.lastMoveToLoc.y = y;

	};
    CanvasRenderingContext2D.prototype.fillStar =function(r, R, rot){
        this.beginPath();
        for(var i = 0; i<5; i++){
            this.lineTo(
                Math.cos((18 + i*72 - rot)/180 *Math.PI) *R +this.lastMoveToLoc.x,
                -Math.sin((18 + i*72 -rot)/180 * Math.PI) * R +this.lastMoveToLoc.y);
            this.lineTo(
                Math.cos((54 + i*72 - rot)/180 * Math.PI) *r +this.lastMoveToLoc.x,
                -Math.sin((54 + i*72 -rot)/180 * Math.PI) *r +this.lastMoveToLoc.y
            );
        }
        this.closePath();
		this.fill();
    }
	window.onload=function() {
        canvas.width = 1024;
        canvas.height = 768;
        //var backCanvas = createBackgroundCanvas();
        //var pattern = context.createPattern(backCanvas, "repeat");
        //context.fillStyle = pattern;
        //context.fillRect(0, 0, 800, 800);
        //var radialGrad = context.createRadialGradient(canvas.width/2, canvas.height, 0, canvas.width/2, canvas.height, canvas.height);
        //radialGrad.addColorStop(0.0, "#035");
        //radialGrad.addColorStop(1.0, "#020202");
        //context.fillStyle = radialGrad;
        //context.fillRect(0, 0, canvas.width, canvas.height);
        //for(var i = 0; i<200; i++){
        //var r = Math.random() * 5 + 5;
        //var x = Math.random() * canvas.width;
        //var y = Math.random() * canvas.height * 0.6;
        //var a = Math.random() * 360;
        //  drawStar(context, x, y , r, "#fb3", a);
        //	}
        // fillRoundRect(context, 150, 150, 500, 500, 10, "#bbada0");
        //for(var i = 0; i < 4; i++){
        //for(var j = 0; j<4; j++){
        //fillRoundRect(context, 170 + i * 120, 170 + j * 120, 100, 100, 6, "#ccc0b3");
        //}
        //}
        //fillMoon(context, 2, 800, 200, 200, 30);
        //fillLand(context);
        //fillText(context);
        //context.fillStyle = 'rgb('+r+','+g+','+b+')';
        //context.beginPath();
        //context.arc(Math.random()*canvas.width, Math.random()*canvas.height, Math.random()*100,0,Math.PI*2);
        //context.fill();
        //context.closePath();
        //}
        //按钮实例化globalCompositeOperation
		//随机圆球运动效果
             for (var i = 0; i < 100; i++) {
            var r = Math.floor(Math.random() * 255);
            var g = Math.floor(Math.random() * 255);
            var b = Math.floor(Math.random() * 255);
            var radius = Math.random() * 50 + 20;
            var aBall = {
                color: 'rgb('+r+','+g+','+b+')',
                radius: radius,
                x: Math.random() * (canvas.width - radius * 2) + radius,
                y: Math.random() * (canvas.height - radius * 2) + radius,
                vx: (Math.random() * 2 ) * Math.pow(-1, Math.floor(Math.random() * 10)),
                vy: (Math.random() * 2 ) * Math.pow(-1, Math.floor(Math.random() * 10))
            };
            balls[i] = aBall;
        }
		setInterval(
               function () {
                    draw(context);
                   update(canvas.width, canvas.height);
                }, 5);
        document.getElementById("canvas-btn").onclick = function(event){
			 if(isMoving){
				 isMoving =false;
				 this.text = "开始运动"
			 }
			 else{
				 isMoving = true;
				 this.text = "停止运动";
			 }
			 return false;
		};
		document.getElementById("white-color-btn").onclick = function(){
			themeColor = "white";
			return false;
		};
		document.getElementById("black-color-btn").onclick = function(){
		    themeColor = "black";
		    return false;
		};
        //探照灯效果
		/*setInterval(function(){
			drawLighter(context);
			updateLighter(canvas.width, canvas.height);
		},50);*/
		//剪纸阴影效果（非零环绕原则）
		context.beginPath();
		context.arc(400, 400, 300, 0, Math.PI*2, false);
		context.arc(400, 400, 150, 0, Math.PI*2,true);
		context.fillStyle = "#058";
		context.shadowColor = "gray";
		context.shadowOffsetX = 10;
		context.shadowOffsetY = 10;
		context.shadowBlur = 10;
		context.fill();
		context.closePath();
		/*for(var i = 0; i<10; i++){
			var aBall = {
				x:Math.random()*canvas.width,
				y:Math.random()*canvas.height,
				r:Math.random() *50 +20
			};
			balls[i] = aBall;
		}
		drawArc();
		canvas.addEventListener("mousemove", detect);*/
		/*context.fillStyle = "#058";
		context.fillStar(150, 300, 30);*/
        };

	//交互功能中的画圆
	function drawArc(){
		for(var i =0; i<balls.length; i++){
			context.beginPath();
			context.arc(balls[i].x, balls[i].y, balls[i].r, 0, Math.PI*2);
			context.fillStyle = "#058";
			context.fill();
		}
	};
	//交互效果的点击圆效果
	function detect(event){
		var x = event.clientX - canvas.getBoundingClientRect().left;
		var y = event.clientY - canvas.getBoundingClientRect().top;
		for(var i = 0; i<balls.length; i++){
			context.beginPath();
			context.arc(balls[i].x, balls[i].y, balls[i].r, 0, Math.PI*2);
			if(context.isPointInPath(x,y)){
				context.fillStyle = "red";
				context.fill();
			}
			else{
			    context.fillStyle = "#058";
			    context.fill();
			}
		}
	}
	    //探照灯画法
	function drawLighter(cxt){
		var canvas = cxt.canvas;

		cxt.clearRect(0, 0, canvas.width, canvas.height);
		cxt.save();

		cxt.beginPath();
		cxt.fillStyle = "#000";
		cxt.fillRect(0, 0, canvas.width, canvas.height);
		cxt.save();
		cxt.translate(searchLight.x, searchLight.y);
		cxt.rotate(rot / 180 * Math.PI);
		cxt.scale(searchLight.radius, searchLight.radius);
		starPath(cxt);
		//cxt.beginPath();
		//cxt.arc(searchLight.x, searchLight.y, searchLight.radius, 0, Math.PI*2);
		cxt.fillStyle = "#FFF";
		cxt.fill();
		cxt.restore();
		cxt.clip();

		cxt.font = "bold 150px Arial";
		cxt.textAlign = "center";
		cxt.textBaseline = "middle";
		cxt.fillStyle = "#058";
		cxt.fillText("CANVAS",canvas.width/2,canvas.height/4);
		cxt.fillText("CANVAS",canvas.width/2,canvas.height/2);
        cxt.fillText("CANVAS",canvas.width/2,canvas.height*3/4);
		cxt.restore()
	}
	//探照灯运动写法
	function updateLighter(canvasWidth, canvasHeight){
        rot += 1;
		searchLight.x += searchLight.vx;
		searchLight.y += searchLight.vy;

		if(searchLight.x - searchLight.radius <= 0){
			searchLight.vx = -searchLight.vx;
			searchLight.x = searchLight.radius;
		}
		if(searchLight.x + searchLight.radius >= canvasWidth){
		    searchLight.vx = -searchLight.vx;
		    searchLight.x = canvasWidth - searchLight.radius;
		}
		if(searchLight.y - searchLight.radius <= 0){
		    searchLight.vy = -searchLight.vy;
		    searchLight.y = searchLight.radius;
		}
		if(searchLight.y + searchLight.radius >= canvasHeight){
		    searchLight.vy = -searchLight.vy;
		    searchLight.y = canvasHeight - searchLight.radius;
		}
	};
        //画圆
   function draw(cxt) {
	   var canvas = cxt.canvas;
	   cxt.clearRect(0, 0, canvas.width, canvas.height);
	   if(themeColor == "black"){
		   cxt.fillStyle = "#000";
		   cxt.fillRect(0, 0, canvas.width, canvas.height);
	   }
	   else{
           cxt.fillStyle = "#FFF";
           cxt.fillRect(0, 0, canvas.width, canvas.height);
	   }
	   for (var i = 0; i < balls.length; i++) {

		   cxt.globalCompositeOperation = "xor";
		   cxt.fillStyle = balls[i].color;
               cxt.beginPath();
               cxt.arc(balls[i].x, balls[i].y, balls[i].radius, 0, Math.PI * 2);
               cxt.closePath();
               cxt.fill();
	   }
        }
        //随机运动
        function update(canvasWidth, canvasHeight) {
       if(isMoving){
           for (var i = 0; i < balls.length; i++) {
               balls[i].x += balls[i].vx;
               balls[i].y += balls[i].vy;
               if (balls[i].x - balls[i].radius <= 0) {
                   balls[i].vx = -balls[i].vx;
                   balls[i].x = balls[i].radius;
               }
               if (balls[i].x + balls[i].radius >= canvasWidth) {
                   balls[i].vx = -balls[i].vx;
                   balls[i].x = canvasWidth - balls[i].radius;
               }
               if (balls[i].y - balls[i].radius <= 0) {
                   balls[i].vy = -balls[i].vy;
                   balls[i].y = balls[i].radius;
               }
               if (balls[i].y + balls[i].radius >= canvasHeight) {
                   balls[i].vy = -balls[i].vy;
                   balls[i].y = canvasHeight - balls[i].radius;
               }
           }
       }
           else{
               balls[i].x = balls[i].x;
               balls[i].y = balls[i].y;
		   }


        };
        //文字的写法
        function fillText(cxt) {
            cxt.font = "normal 40px 微软雅黑 arial";
            var textLinearG = cxt.createLinearGradient(0, 650, 1000, 650);
            textLinearG.addColorStop(0.0, "#D9E56D");
            textLinearG.addColorStop(1.0, "#258BFD");
            cxt.fillStyle = textLinearG;
            cxt.strokeStyle = textLinearG;
            cxt.textalign = "left";
            cxt.shadowColor = "#4E5052";
            cxt.shadowOffsetX = 10;
            cxt.shadowOffsetY = 10;
            cxt.shadowBlur = 2;
            cxt.fillText("欢迎大家学习《Canvas绘图接口详解》", 40, 650);
            cxt.strokeText("－－liuyubobobo @慕课网 荣誉出品", 300, 720);
        };
        //绿地的写法
        function fillLand(cxt) {
            cxt.save();
            cxt.beginPath();
            cxt.moveTo(0, 600);
            cxt.bezierCurveTo(540, 400, 800, 800, 1200, 600);
            cxt.lineTo(1200, 800);
            cxt.lineTo(0, 800);
            cxt.closePath();
            var landStyle = cxt.createLinearGradient(0, 800, 0, 0);
            landStyle.addColorStop(0.0, "#030");
            landStyle.addColorStop(1.0, "#580");
            cxt.fillStyle = landStyle;
            cxt.fill();
            cxt.restore();
        }

        // 月亮的写法
        function fillMoon(cxt, d, x, y, R, rot, /*optional*/fillColor) {
            cxt.save();
            cxt.translate(x, y);
            cxt.rotate(rot * Math.PI / 180);
            cxt.scale(R, R);
            pathMoon(cxt, d);
            cxt.fillStyle = fillColor || "#fb5";
            cxt.fill();
            cxt.restore();
        }

        //月亮的写法:路径
        function pathMoon(cxt, d) {
            cxt.beginPath();
            cxt.arc(0, 0, 1, 0.5 * Math.PI, Math.PI * 1.5, true);
            cxt.moveTo(0, -1);
            //cxt.arcTo(d, 0, 0, 1, dis(0, -1, d, 0) /d);
            cxt.quadraticCurveTo(1.2, 0, 0, 1);
            cxt.closePath();
        };
        //计算两点之间距离公式
        function dis(x1, x2, y1, y2) {
            return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
        }

        function strokeRoundRect(cxt, x, y, width, height, radius, /*optional*/lineWidth, /*optional*/strokeColor) {
            if (2 * radius > width || 2 * radius > height) {
                return;
            }
            cxt.save();
            cxt.translate(x, y);
            pathRoundRect(cxt, width, height, radius);
            cxt.lineWidth = lineWidth || 1;
            cxt.strokeStyle = strokeColor || "black";
            cxt.stroke();
            cxt.restore();
        }

        function fillRoundRect(cxt, x, y, width, height, radius, /*optional*/fillColor) {
            if (2 * radius > width || 2 * radius > height) {
                return;
            }
            cxt.save();
            cxt.translate(x, y);
            pathRoundRect(cxt, width, height, radius);
            cxt.fillStyle = fillColor || "black";
            cxt.fill();
            cxt.restore();
        };
        function pathRoundRect(cxt, width, height, radius) {
            cxt.beginPath();
            cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
            cxt.lineTo(radius, height);
            cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
            cxt.lineTo(0, radius);
            cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
            cxt.lineTo(radius, 0);
            cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
            cxt.closePath();
        };
        function createBackgroundCanvas() {
            var backCanvas = document.createElement("canvas");
            backCanvas.width = 100;
            backCanvas.height = 100;
            var backCanvasContext = backCanvas.getContext("2d");
            drawStar(backCanvasContext, 50, 50, 50, "#035", 0);
            return backCanvas;
        }

        function drawStar(cxt, x, y, r, fillColor, rotation) {
            cxt.save();
            cxt.translate(x, y);
            cxt.rotate(rotation / 180 * Math.PI);
            cxt.scale(r, r);
            starPath(cxt);
            cxt.fillStyle = fillColor;
            cxt.fill();
            cxt.restore();

        };
        function starPath(cxt) {
            cxt.beginPath();
            for (var i = 0; i < 5; i++) {
                cxt.lineTo(
                    Math.cos((18 + i * 72 ) / 180 * Math.PI),
                    -Math.sin((18 + i * 72 ) / 180 * Math.PI)
                );
                cxt.lineTo(
                    Math.cos((54 + i * 72 ) / 180 * Math.PI) * 0.5,
                    -Math.sin((54 + i * 72 ) / 180 * Math.PI) * 0.5
                );
            }
            cxt.closePath();
        }

</script>
</body>
</html>